package com.dlc.hardwareprotocol.serialport;


import com.dlc.hardwareprotocol.Protocol;
import com.dlc.hardwareprotocol.serialport.command.RecvCommand;
import com.dlc.hardwareprotocol.serialport.command.recv.RecvBA;
import com.dlc.hardwareprotocol.serialport.command.recv.RecvUnknown;
import com.dlc.hardwareprotocol.serialport.utils.ByteUtil;
import com.dlc.hardwareprotocol.serialport.utils.LogPlus;
import com.licheedev.serialworker.core.DataReceiver;
import com.licheedev.serialworker.core.ValidData;

import java.nio.ByteBuffer;


public class MainDataReceiver implements DataReceiver<RecvCommand> {

    private final ByteBuffer mByteBuffer;

    public MainDataReceiver() {
        mByteBuffer = ByteBuffer.allocate(1024);
        mByteBuffer.clear();
    }

    @Override
    public void onReceive(ValidData validData, byte[] bytes, int offset, int length) {
        try {
            LogPlus.e("控制板接收数据=" + ByteUtil.bytes2HexStr(bytes, offset, length));
            byte b;
            int readable;
            mByteBuffer.put(bytes, 0, length);
            mByteBuffer.flip();
            out:
            while ((readable = mByteBuffer.remaining()) >= Protocol.MIN_PACK_LEN) {
                mByteBuffer.mark(); // 标记一下开始的位置
                int frameStart = mByteBuffer.position();
                byte[] dataFrameHead = Protocol.FRAME_HEAD;
                for (byte head : dataFrameHead) {
                    b = mByteBuffer.get();
                    if (b != head) { // 不满足帧头，就跳到第二位，重新开始
                        mByteBuffer.position(frameStart + 1);
                        continue out;
                    }
                }

                byte[] dataLengthBytes = new byte[1];
                dataLengthBytes[0] = mByteBuffer.get(4);//第5个字节 为 data Length send bytes: hex

                int dataLength = ByteUtil.byteToInt(dataLengthBytes);

                int total = Protocol.MIN_PACK_LEN + dataLength - 1 - 1;
                // 如果可读数据小于总数据长度，表示不够,还有数据没接收
                if (readable < total) {
                    // 重置一下要处理的位置,并跳出循环
                    mByteBuffer.reset();
                    break;
                }
                mByteBuffer.reset();
                // 拿到整个包
                byte[] allPack = new byte[total];
                mByteBuffer.get(allPack);

                byte recvCheck = allPack[allPack.length - 1];//
                byte myCheck = ByteUtil.getXOR(allPack, 0, allPack.length - 1);
                if (myCheck == recvCheck) { // 校验通过
                    //LogPlus.d("#####校验通过,allPack:" + ByteUtil.bytes2HexStr(allPack));
                    validData.add(allPack);
                }
            }
        } catch (Exception e) {
            LogPlus.e(e.getMessage(), e);
        } finally {
            // 最后清掉之前处理过的不合适的数据
            mByteBuffer.compact();
        }
    }

    @Override
    public RecvCommand adaptReceive(byte[] allPack) {
        RecvCommand recvCommand = null;
        try {
            final int cmd = allPack[5]; /*命令码*/
            // 数据部分的长度
            int dataLen;
            byte[] dataLengthBytes = new byte[1];
            dataLengthBytes[0] = allPack[4];
            dataLen = ByteUtil.byteToInt(dataLengthBytes);
            // 数据域
            final byte[] data = new byte[dataLen - 1 - 1];//1字节，包括命令码、协议版本和数据域的长度
            final int DATA_LENGTH = 0;//0-n length
            int srcPos = 2 + 1 + 1 + 1 + 1 + 1/*+ DATA_LENGTH + 1*/;
            System.arraycopy(allPack, srcPos, data, 0, data.length);/*从该字节位置开始为数据部分*/
            //分发数据
            switch (cmd) {
                case Protocol.COMMAND_BA:
                    recvCommand = new RecvBA(allPack, data, cmd);
                    break;
                default:
                    recvCommand = new RecvUnknown(allPack, data, cmd);
                    break;
            }
        } catch (Exception e) {
            // 保险起见，try-catch一下
            e.printStackTrace();
        }
        return recvCommand;
    }

    @Override
    public void resetCache() {
        mByteBuffer.clear();
    }
}
